﻿using System;

/// <summary>
/// C# Date Differential
/// Object that calculates the this.Days, months, and this.Years... since or until another earlierDate.
/// </summary>
namespace MikeKappel.Com.CS.Model
{

    /// <summary>
    /// DateDifferential is for returning the difference 
    /// between two dates in the year, month, and day format
    /// </summary>
    public class DateDifferential
    {
        /// <summary>
        /// Count Up from date, Countdown from date, or Equal  
        /// </summary>
        public enum DateDifferentialType
        {
            /// <summary>
            ///  Count Up from date
            ///  Time since date
            /// </summary>
            Ascending,
            /// <summary>
            ///  Countdown to date
            ///  Time until date
            /// </summary>
            Descending,
            /// <summary>
            /// Dates are the same
            /// </summary>
            Equal
        }
        public enum DetailType
        {
            /// <summary>
            /// Include this.Days
            /// </summary>
            Days,
            /// <summary>
            /// Include this.Hours
            /// </summary>
            Hours,
            /// <summary>
            /// Include this.Hours
            /// </summary>
            Minutes,
            /// <summary>
            /// Include this.Seconds
            /// </summary>
            Seconds,
            /// <summary>
            /// Include this.Milliseconds
            /// </summary>
            Milliseconds
        }

        /// <summary>
        /// Countdown, Count Up, or Equal
        /// </summary>
        public DateDifferentialType Type { get; private set; }

        /// <summary>
        /// The amount of detail that should be shown
        /// Auto, Days, Hours, Minutes, Seconds, or Milliseconds
        /// </summary>
        public DetailType AmountOfDetail { get; private set; }

        /// <summary>
        /// Millennium part of the difference between dates
        /// </summary>
        public Int32? Millennia { get; private set; }

        /// <summary>
        /// Century part of the difference between dates
        /// </summary>
        public Int32? Centuries { get; private set; }

        /// <summary>
        /// Decade part of the difference between dates
        /// </summary>
        public Int32? Decades { get; private set; }

        /// <summary>
        /// Year part of the difference between dates
        /// </summary>
        public Int32? Years { get; private set; }

        /// <summary>
        /// Month part of the difference between dates
        /// </summary>
        public Int32? Months { get; private set; }

        /// <summary>
        /// Day part of the difference between dates
        /// </summary>
        public Int32? Weeks { get; private set; }

        /// <summary>
        /// Day part of the difference between dates
        /// </summary>
        public Int32? Days { get; private set; }

        /// <summary>
        /// Hour part of the difference between dates
        /// </summary>
        public Int32? Hours { get; private set; }

        /// <summary>
        /// Minute part of the difference between dates
        /// </summary>
        public Int32? Minutes { get; private set; }

        /// <summary>
        /// Second part of the difference between dates
        /// </summary>
        public Int32? Seconds { get; private set; }

        /// <summary>
        /// Millisecond part of the difference between dates
        /// </summary>
        public Int32? Milliseconds { get; private set; }

        /// <summary>
        /// Total difference between dates
        /// </summary>
        public TimeSpan Difference { get; private set; }

        /// <summary>
        /// Earlier of the two dates
        /// </summary>
        public DateTime EarlierDate { get; private set; }

        /// <summary>
        /// Later of the two dates
        /// </summary>
        public DateTime LaterDate { get; private set; }

        /// <summary>
        /// Time betwween a date and the current date
        /// Date is calculated against current date and time
        /// </summary>
        /// <param name="date">Date to calculate against current date</param>
        public DateDifferential(DateTime date)
            : this(date, DateTime.Now)
        {

        }

        /// <summary>
        /// Time betwween a date and the current date
        /// Date is calculated against current date and time
        /// <example>
        /// Example: Countdown to date 
        /// DateDifferential df = new DateDifferential(new DateTime(3500, 1, 1), DateDifferential.DetailType.Days);
        /// Response.Write(df.ToString()); 1 Millennium, 4 Centuries, 9 Decades, 2 months, 3 this.Weeks, 5 this.Days 
        /// </example>
        /// </summary>
        /// <param name="date">Date to calculate against current date</param>
        /// <param name="detail">Level of detail</param>
        public DateDifferential(DateTime date, DetailType detail)
            : this(date, DateTime.Now, detail)
        {

        }

        /// <summary>
        /// Time from one date to another
        /// </summary>
        /// <param name="firstDate">First date</param>
        /// <param name="secondDate">Secound date</param>
        public DateDifferential(DateTime firstDate, DateTime secondDate)
            : this(firstDate, secondDate, DetailType.Milliseconds)
        {

        }

        /// <summary>
        /// Time from one date to another
        /// </summary>
        /// <param name="firstDate">First date</param>
        /// <param name="secondDate">Secound date</param>
        /// <param name="detail">Level of detail</param>
        public DateDifferential(DateTime firstDate, DateTime secondDate, DetailType detail)
            : this(firstDate, secondDate, true, true, true, true, true, true, true, detail)
        {

        }

        /// <summary>
        /// Time from one date to another
        /// </summary>
        /// <example>
        /// Example: Calculate age or time since birth 
        /// DateDifferential df = new DateDifferential(new DateTime(1978, 4, 19),DateTime.Now,false,false,false,true,true,false,true, DateDifferential.DetailType.Days);
        /// Response.Write(df.ToString()); 
        /// Result "31 this.Years, 5 months, 16 this.Days"
        /// </example>
        /// <param name="firstDate">First date</param>
        /// <param name="secondDate">Secound date</param>
        /// <param name="CalculateMillennia">Calculate Millennia</param>
        /// <param name="CalculateCenturies">Calculate Centuries</param>
        /// <param name="CalculateDecades">Calculate Decades</param>
        /// <param name="CalculateYears">Calculate Years</param>
        /// <param name="CalculateMonths">Calculate Months</param>
        /// <param name="CalculateWeeks">Calculate Weeks</param>
        /// <param name="CalculateDays">Calculate Days</param>
        /// <param name="detail">Level of detail</param>
        public DateDifferential(DateTime firstDate, DateTime secondDate,
            Boolean CalculateMillennia,
            Boolean CalculateCenturies,
            Boolean CalculateDecades,
            Boolean CalculateYears,
            Boolean CalculateMonths,
            Boolean CalculateWeeks,
            Boolean CalculateDays,
            DetailType detail)
        {
            this.AmountOfDetail = detail;
            if (detail.CompareTo(DetailType.Milliseconds) < 0
                && (firstDate.Millisecond > 0 || secondDate.Millisecond > 0))
            {
                firstDate.AddMilliseconds(-firstDate.Millisecond);
                secondDate.AddMilliseconds(-secondDate.Millisecond);
                firstDate.AddSeconds(1);
                secondDate.AddSeconds(1);
            }
            if (detail.CompareTo(DetailType.Seconds) < 0
                && (firstDate.Second > 0 || secondDate.Second > 0))
            {
                firstDate.AddSeconds(-firstDate.Second);
                secondDate.AddSeconds(-secondDate.Second);
                firstDate.AddMinutes(1);
                secondDate.AddMinutes(1);
            }
            if (detail.CompareTo(DetailType.Minutes) < 0
                && (firstDate.Minute > 0 || secondDate.Minute > 0))
            {
                firstDate.AddMinutes(-firstDate.Minute);
                secondDate.AddMinutes(-secondDate.Minute);
                firstDate.AddHours(1);
                secondDate.AddHours(1);
            }
            if (detail.CompareTo(DetailType.Hours) < 0
                && (firstDate.Hour > 0 || secondDate.Hour > 0))
            {
                firstDate.AddHours(-firstDate.Hour);
                secondDate.AddHours(-secondDate.Hour);
                firstDate.AddDays(1);
                secondDate.AddDays(1);
            }


            if (firstDate.Year == secondDate.Year
                 && firstDate.Month == secondDate.Month
                 && firstDate.Day == secondDate.Day
                 && firstDate.Hour == secondDate.Hour
                 && firstDate.Minute == secondDate.Minute
                 && firstDate.Second == secondDate.Second
                 && firstDate.Millisecond == secondDate.Millisecond)
            {
                this.Type = DateDifferentialType.Equal;
            }
            else if (firstDate > secondDate)
            {
                this.Type = DateDifferentialType.Descending;
            }
            else
            {
                this.Type = DateDifferentialType.Ascending;
            }

            EarlierDate = (firstDate > secondDate) ? secondDate : firstDate;
            LaterDate = (firstDate > secondDate) ? firstDate : secondDate;

            if (this.Type == DateDifferentialType.Equal)
                return;

            Difference = LaterDate.Subtract(EarlierDate);

            DateTime tempLaterDate = LaterDate;

            if (Difference.TotalDays >= 365249 && CalculateMillennia)
            {
                this.Millennia = 0;
                // getting number of millennium
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Millennia++;
                    tempLaterDate = tempLaterDate.AddYears(-1000);
                }
                tempLaterDate = tempLaterDate.AddYears(1000);
                this.Millennia--;
            }

            if (Difference.TotalDays >= 36524 && CalculateCenturies)
            {
                this.Centuries = 0;
                // getting number of this.Centuries
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Centuries++;
                    tempLaterDate = tempLaterDate.AddYears(-100);
                }
                tempLaterDate = tempLaterDate.AddYears(100);
                this.Centuries--;
            }

            if (Difference.TotalDays >= 3653 && CalculateDecades)
            {
                Decades = 0;
                // getting number of this.Years
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    Decades++;
                    tempLaterDate = tempLaterDate.AddYears(-10);
                }
                tempLaterDate = tempLaterDate.AddYears(10);
                Decades--;
            }

            if (Difference.TotalDays >= 365 && CalculateYears)
            {
                this.Years = 0;
                // getting number of this.Years
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Years++;
                    tempLaterDate = tempLaterDate.AddYears(-1);
                }
                tempLaterDate = tempLaterDate.AddYears(1);
                this.Years--;
            }

            if (CalculateMonths)
            {
                Months = 0;
                // getting number of months
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    Months++;
                    tempLaterDate = tempLaterDate.AddMonths(-1);
                }
                tempLaterDate = tempLaterDate.AddMonths(1);
                Months--;
            }

            if (CalculateWeeks)
            {
                this.Weeks = 0;
                // getting number of this.Weeks
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Weeks++;
                    tempLaterDate = tempLaterDate.AddDays(-7);
                }
                tempLaterDate = tempLaterDate.AddDays(7);
                this.Weeks--;
            }

            if (CalculateDays)
            {
                this.Days = 0;
                // getting number of this.Days
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Days++;
                    tempLaterDate = tempLaterDate.AddDays(-1);
                }
                tempLaterDate = tempLaterDate.AddDays(1);
                this.Days--;
            }

            if (detail.CompareTo(DetailType.Hours) >= 0)
            {
                this.Hours = 0;
                // getting number of this.Hours
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Hours++;
                    tempLaterDate = tempLaterDate.AddHours(-1);
                }
                tempLaterDate = tempLaterDate.AddHours(1);
                this.Hours--;
            }

            if (detail.CompareTo(DetailType.Minutes) >= 0)
            {
                this.Minutes = 0;
                // getting number of this.Minutes
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Minutes++;
                    tempLaterDate = tempLaterDate.AddMinutes(-1);
                }
                tempLaterDate = tempLaterDate.AddMinutes(1);
                this.Minutes--;
            }

            if (detail.CompareTo(DetailType.Seconds) >= 0)
            {
                this.Seconds = 0;
                // getting number of this.Seconds
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Seconds++;
                    tempLaterDate = tempLaterDate.AddSeconds(-1);
                }
                tempLaterDate = tempLaterDate.AddSeconds(1);
                this.Seconds--;
            }

            if (detail.CompareTo(DetailType.Milliseconds) >= 0)
            {
                this.Milliseconds = 0;
                // getting number of this.Milliseconds
                while (tempLaterDate.CompareTo(EarlierDate) >= 0)
                {
                    this.Milliseconds++;
                    tempLaterDate = tempLaterDate.AddMilliseconds(-1);
                }
                tempLaterDate = tempLaterDate.AddMilliseconds(1);
                this.Milliseconds--;
            }

        }

        /// <summary>
        /// Create Differential based on the addtion or removal of time 
        /// </summary>
        /// <param name="MinDateDiff">Date Diffrence based on DateTime.MinValue</param>
        /// <param name="differentialType">Ascending (add to date) or Descending (subtract to date)</param>
        /// <returns>Date Differential that represents the difference in time</returns>
        public static DateDifferential CreateDifferential(DateTime minDateDiff, DateDifferentialType differentialType)
        {
            return CreateDifferential(minDateDiff, DateTime.Now, differentialType);
        }

        /// <summary>
        /// Create Differential based on the addtion or removal of time 
        /// </summary>
        /// <param name="MinDateDiff">Date Diffrence based on DateTime.MinValue</param>
        /// <param name="startingDate">Date to base generated date on</param>
        /// <param name="differentialType">Ascending (add to date) or Descending (subtract to date)</param>
        /// <returns>Date Differential that represents the difference in time</returns>
        public static DateDifferential CreateDifferential(DateTime minDateDiff, DateTime  startingDate, DateDifferentialType differentialType)
        {
            return CreateDifferential(0, 0, 0, minDateDiff.Year - DateTime.MinValue.Year, minDateDiff.Month - DateTime.MinValue.Month, 0, minDateDiff.Day - DateTime.MinValue.Day, minDateDiff.Hour - DateTime.MinValue.Hour, minDateDiff.Minute - DateTime.MinValue.Minute, minDateDiff.Second - DateTime.MinValue.Second, minDateDiff.Millisecond - DateTime.MinValue.Millisecond, differentialType, DetailType.Milliseconds, startingDate);
        }

        /// <summary>
        /// Create Differential based on the addtion or removal of time 
        /// </summary>
        /// <param name="millennia">Millennium Offset</param>
        /// <param name="centuries">Century Offset</param>
        /// <param name="decades">Decade Offset</param>
        /// <param name="years">Year Offset</param>
        /// <param name="months">Month Offset</param>
        /// <param name="weeks">Week Offset</param>
        /// <param name="days">Day Offset</param>
        /// <param name="hours">Hour Offset</param>
        /// <param name="minutes">Minute Offset</param>
        /// <param name="seconds">Second Offset</param>
        /// <param name="milliseconds">Millisecond Offset</param>
        /// <param name="differentialType">Ascending (add to date) or Descending (subtract to date)</param>
        /// <returns>Date Differential that represents the difference in time</returns>
        public static DateDifferential CreateDifferential(Int32 millennia, Int32 centuries, Int32 decades, Int32 years, Int32 months, Int32 weeks, Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds, DateDifferentialType differentialType)
        {
            return CreateDifferential(millennia, centuries, decades, years, months, weeks, days, hours, minutes, seconds, milliseconds, differentialType, DetailType.Milliseconds , DateTime.Now);
        }

        /// <summary>
        /// Create Differential based on the addtion or removal of time 
        /// </summary>
        /// <param name="millennia">Millennium Offset</param>
        /// <param name="centuries">Century Offset</param>
        /// <param name="decades">Decade Offset</param>
        /// <param name="years">Year Offset</param>
        /// <param name="months">Month Offset</param>
        /// <param name="weeks">Week Offset</param>
        /// <param name="days">Day Offset</param>
        /// <param name="hours">Hour Offset</param>
        /// <param name="minutes">Minute Offset</param>
        /// <param name="seconds">Second Offset</param>
        /// <param name="milliseconds">Millisecond Offset</param>
        /// <param name="differentialType">Ascending (add to date) or Descending (subtract to date)</param>
        /// <param name="detail">Level of detail</param>
        /// <returns>Date Differential that represents the difference in time</returns>
        public static DateDifferential CreateDifferential(Int32 millennia, Int32 centuries, Int32 decades, Int32 years, Int32 months, Int32 weeks, Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds, DateDifferentialType differentialType, DetailType detail)
        {
            return CreateDifferential(millennia, centuries, decades, years, months, weeks, days, hours, minutes, seconds, milliseconds, differentialType, detail, DateTime.Now);
        }
        
        /// <summary>
        /// Create Differential based on the addtion or removal of time 
        /// </summary>
        /// <param name="millennia">Millennium Offset</param>
        /// <param name="centuries">Century Offset</param>
        /// <param name="decades">Decade Offset</param>
        /// <param name="years">Year Offset</param>
        /// <param name="months">Month Offset</param>
        /// <param name="weeks">Week Offset</param>
        /// <param name="days">Day Offset</param>
        /// <param name="hours">Hour Offset</param>
        /// <param name="minutes">Minute Offset</param>
        /// <param name="seconds">Second Offset</param>
        /// <param name="milliseconds">Millisecond Offset</param>
        /// <param name="differentialType">Ascending (add to date) or Descending (subtract to date)</param>
        /// <param name="detail">Level of detail</param>
        /// <returns>Date Differential that represents the difference in time</returns>
        public static DateDifferential CreateDifferential(Int32 millennia, Int32 centuries, Int32 decades, Int32 years, Int32 months, Int32 weeks, Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds, DateDifferentialType differentialType, DetailType detail, DateTime startingDate)
        {
            return CreateDifferential(millennia, centuries, decades, years, months, weeks, days, hours, minutes, seconds, milliseconds, differentialType, detail, DateTime.Now, true, true, true, true, true, true, true);
        }

        /// <summary>
        /// Create Differential based on the addtion or removal of time 
        /// </summary>
        /// <param name="millennia">Millennium Offset</param>
        /// <param name="centuries">Century Offset</param>
        /// <param name="decades">Decade Offset</param>
        /// <param name="years">Year Offset</param>
        /// <param name="months">Month Offset</param>
        /// <param name="weeks">Week Offset</param>
        /// <param name="days">Day Offset</param>
        /// <param name="hours">Hour Offset</param>
        /// <param name="minutes">Minute Offset</param>
        /// <param name="seconds">Second Offset</param>
        /// <param name="milliseconds">Millisecond Offset</param>
        /// <param name="differentialType">Ascending (add to date) or Descending (subtract to date)</param>
        /// <param name="detail">Level of detail</param>
        /// <param name="startingDate">Date to base generated date on</param>
        /// <param name="CalculateMillennia">Calculate Millennia</param>
        /// <param name="CalculateCenturies">Calculate Centuries</param>
        /// <param name="CalculateDecades">Calculate Decades</param>
        /// <param name="CalculateYears">Calculate Years</param>
        /// <param name="CalculateMonths">Calculate Months</param>
        /// <param name="CalculateWeeks">Calculate Weeks</param>
        /// <param name="CalculateDays">Calculate Days</param>
        /// <returns>Date Differential that represents the difference in time</returns>
        public static DateDifferential CreateDifferential(Int32 millennia, Int32 centuries, Int32 decades, Int32 years, Int32 months, Int32 weeks, Int32 days, Int32 hours, Int32 minutes, Int32 seconds, Int32 milliseconds, DateDifferentialType differentialType, DetailType detail, DateTime startingDate,
                        Boolean calculateMillennia,Boolean calculateCenturies,Boolean calculateDecades,Boolean calculateYears,Boolean calculateMonths,Boolean calculateWeeks,Boolean calculateDays)
        {
            DateTime tempLaterDate = startingDate;
            DateTime tempEarlierDate = startingDate;
            if (differentialType == DateDifferentialType.Ascending)
            {

                tempLaterDate = tempLaterDate.AddYears(millennia * 1000);
                tempLaterDate = tempLaterDate.AddYears(centuries * 100);
                tempLaterDate = tempLaterDate.AddYears(decades * 10);
                tempLaterDate = tempLaterDate.AddYears(years);
                tempLaterDate = tempLaterDate.AddMonths(months);
                tempLaterDate = tempLaterDate.AddDays(weeks * 7);
                tempLaterDate = tempLaterDate.AddHours(hours);
                tempLaterDate = tempLaterDate.AddMinutes(minutes);
                tempLaterDate = tempLaterDate.AddSeconds(seconds);
                tempLaterDate = tempLaterDate.AddMilliseconds(milliseconds);
                return new DateDifferential(tempLaterDate, tempEarlierDate, calculateMillennia, calculateCenturies, calculateDecades, calculateYears, calculateMonths, calculateWeeks,calculateDays, detail);
            }
            if (differentialType == DateDifferentialType.Descending)
            {
                tempEarlierDate = tempEarlierDate.AddYears(-millennia * 1000);
                tempEarlierDate = tempEarlierDate.AddYears(-centuries * 100);
                tempEarlierDate = tempEarlierDate.AddYears(-decades * 10);
                tempEarlierDate = tempEarlierDate.AddYears(-years);
                tempEarlierDate = tempEarlierDate.AddMonths(-months);
                tempEarlierDate = tempEarlierDate.AddDays(-weeks * 7);
                tempEarlierDate = tempEarlierDate.AddHours(-hours);
                tempEarlierDate = tempEarlierDate.AddMinutes(-minutes);
                tempEarlierDate = tempEarlierDate.AddSeconds(-seconds);
                tempEarlierDate = tempEarlierDate.AddMilliseconds(-milliseconds);
                return new DateDifferential(tempEarlierDate, tempLaterDate, calculateMillennia, calculateCenturies, calculateDecades, calculateYears, calculateMonths, calculateWeeks, calculateDays, detail);
            }
            else
            {
                return new DateDifferential(tempEarlierDate, tempLaterDate, calculateMillennia, calculateCenturies, calculateDecades, calculateYears, calculateMonths, calculateWeeks, calculateDays, detail);
            }
        }

        /// <summary>
        /// Description of the difference in dates in detail
        /// </summary>
        /// <returns></returns>
        public override String ToString()
        {
            String textResult = "";
            if (Millennia.HasValue && Millennia > 0)
                textResult += Millennia.ToString() + " Millenni" + ((Millennia > 1) ? "a" : "um");

            if (Centuries.HasValue && Centuries > 0)
                textResult += (textResult != "" ? ", " : "") + Centuries.ToString() + " Centur" + ((Centuries > 1) ? "ies" : "y");

            if (Decades.HasValue && Decades > 0)
                textResult += (textResult != "" ? ", " : "") + Decades.ToString() + " Decade" + ((Decades > 1) ? "s" : "");

            if (Years.HasValue && Years > 0)
                textResult += (textResult != "" ? ", " : "") + Years.ToString() + " year" + ((Years > 1) ? "s" : "");

            if (Months.HasValue && Months > 0)
                textResult += (textResult != "" ? ", " : "") + Months.ToString() + " month" + ((Months > 1) ? "s" : "");

            if (Weeks.HasValue && Weeks > 0)
                textResult += (textResult != "" ? ", " : "") + Weeks.ToString() + " week" + ((Weeks > 1) ? "s" : "");

            if (Days.HasValue && Days > 0)
                textResult += (textResult != "" ? ", " : "") + Days.ToString() + " day" + ((Days > 1) ? "s" : "");

            if (Hours.HasValue && Hours > 0)
                textResult += (textResult != "" ? ", " : "") + Hours.ToString() + " Hour" + ((Hours > 1) ? "s" : "");

            if (Minutes.HasValue && Minutes > 0)
                textResult += (textResult != "" ? ", " : "") + Minutes.ToString() + " Minute" + ((Minutes > 1) ? "s" : "");

            if (Seconds.HasValue && Seconds > 0)
                textResult += (textResult != "" ? ", " : "") + Seconds.ToString() + " Second" + ((Seconds > 1) ? "s" : "");

            if (Milliseconds.HasValue && Milliseconds > 0)
                textResult += (textResult != "" ? ", " : "") + Milliseconds.ToString() + " Millisecond" + ((Milliseconds > 1) ? "s" : "");

            String[] textResultSplit = textResult.Split(',');
            if (textResultSplit.Length > 1)
                textResult = textResult.Replace(((textResultSplit.Length == 2) ? "," : "") + textResultSplit[textResultSplit.Length - 1], " and " + textResultSplit[textResultSplit.Length - 1]);

            return textResult;
        }
    }
}